package com.it.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;

import com.it.model.Book;
import com.it.model.Chapter;
import com.it.service.IBookService;
import com.it.service.IChapterService;
import com.it.service.biz.ChapterBiz;
import com.it.utils.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @desc:
 * @author: panxiyi
 * @date: 2023/4/12 7:54 下午
 */

@RestController
@RequestMapping("books")
public class BookController {

    // 创建记录日志对象
    private static final Logger Log = LoggerFactory.getLogger(BookController.class);

    @Autowired
    private IBookService bookService;

    @Value("${file.upload.directory}")
    private String uploadDir;

    private final static Object lockObj = new Object();

    @Autowired
    private ChapterBiz chapterBiz;

    @Autowired
    private IChapterService chapterService;

    @GetMapping
    public R getAll() {
        return new R(true, bookService.list());
    }


    @PostMapping
    public R save(@RequestBody Book book) {

        if (book.getId() == null || book.getId().longValue() == 0L) {
//            synchronized (lockObj) {
//                List<Book> books = bookService.list();
//                Optional<Book> first = books.stream().sorted(Comparator.comparing(Book::getId).reversed()).findFirst();
//                Long nextId = first.get().getId() + 1;
//
//            }
            book.setId(SnowFlake.getInstance().genUuid());
        }
        return new R(bookService.save(book));
    }

    @PutMapping
    public R update(@RequestBody Book book) {
        return new R(bookService.updateById(book));
    }

    @PostMapping(value = "/update_book")
    public R updateBook(Book book,
                        @RequestParam(value = "file", required = false) MultipartFile file) {
        Logs.common.info(Pair.of("message", "update_book"), Pair.of("book", JSON.toJSONString(book)), Pair.of("file", file != null? file.getOriginalFilename() : "file is null"));
        if (file != null) {
            try {
                // 获取原始文件名
                String originalFilename = file.getOriginalFilename();
                if (originalFilename != null) {
                    // 获取文件后缀名
                    String fileExtension = originalFilename.substring(originalFilename.lastIndexOf('.') + 1);
                    // 保存文件到不同的目录
                    Path destination;
                    if ("zip".equalsIgnoreCase(fileExtension)) {
                        destination = Paths.get(uploadDir, "archives", originalFilename);
                        // 创建目标文件夹，存在不做任何操作
                        Files.createDirectories(destination.getParent());
                        // 将上传的文件保存到目标路径
                        Files.copy(file.getInputStream(), destination, StandardCopyOption.REPLACE_EXISTING);
                        // 如果是压缩文件，则解压
                        if ("zip".equalsIgnoreCase(fileExtension)) {
                            //unzip(destination, destination.getParent());
                            Path filePath = destination;
                            List<Chapter> chapters = chapterBiz.decompressAndExtractBooks(filePath, book.getId());
                            if (!CollectionUtils.isEmpty(chapters)) {
                                // 把库里现有的该书籍的章节数据删除
                                QueryWrapper<Chapter> qw = new QueryWrapper<>();
                                qw.eq("book_id", book.getId());
                                List<Chapter> list = chapterService.list(qw);
                                if (!CollectionUtils.isEmpty(list)) {
                                    List<Long> ids = list.stream().map(Chapter::getId).collect(Collectors.toList());
                                    chapterService.removeBatchByIds(ids);
                                }
                            }
                            Logs.common.info(Pair.of("chapters", JSON.toJSONString(chapters)));
                            try {
                                boolean res = chapterService.saveBatch(chapters);
                                Logs.common.info(Pair.of("message", "upload res"), Pair.of("res", res), Pair.of("chapters", JSON.toJSONString(chapters)));
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }

                    }

                }

                //return new ResponseEntity<>("File uploaded successfully: " + fileName, HttpStatus.OK);
            } catch (IOException e) {
                e.printStackTrace();
                //return new ResponseEntity<>("Failed to upload file: " + fileName, HttpStatus.INTERNAL_SERVER_ERROR);
            } catch (Exception exception) {
                exception.printStackTrace();
            }
        }


        return new R(bookService.updateById(book));
    }

    @DeleteMapping("{id}")
    public R delete(@PathVariable Long id) {
        return new R(bookService.delete(id));
    }

    @GetMapping("{id}")
    public R getById(@PathVariable Long id) {
        return new R(true, bookService.getById(id));
    }

    @GetMapping("{currentPage}/{pageSize}")
    public R getByPage(@PathVariable int currentPage, @PathVariable int pageSize,
                       @RequestParam(name = "type", defaultValue = "") String type,
                       @RequestParam(name = "name", defaultValue = "") String name,
                       @RequestParam(name = "description", defaultValue = "") String description) {

        Logs.common.info(Pair.of("type", type), Pair.of("name", name), Pair.of("description", description));
        IPage<Book> page = bookService.getByPage(currentPage, pageSize, type, name, description);
        if (page.getPages() < currentPage) {
            page = bookService.getByPage((int)page.getPages(), pageSize, type, name, description);
        }
        //
        return new R(true, page);
    }
}
